package models

import (
	"fmt"
	"strconv"
	"time"

	"github.com/beego/beego/v2/client/orm"
	"github.com/beego/beego/v2/core/logs"
)

// Order 订单模型
type Order struct {
	BaseModel
	OrderNo           string `orm:"size(64)" json:"order_no"`              // 订单号
	UserId            int64  `orm:"index" json:"user_id"`                  // 用户ID
	MemberId          int64  `orm:"index" json:"member_id"`                // 会员ID
	UserName          string `orm:"size(64)" json:"user_name"`             // 用户姓名
	Phone             string `orm:"size(20)" json:"phone"`                 // 手机号
	Status            int8   `orm:"default(0)" json:"status"`              // 状态：0：已支付 1:待确认 2:已确认 3:已完成 4:已取消
	TotalAmount       int64  `json:"total_amount"`                         // 总金额（分）
	PayAmount         int64  `json:"pay_amount"`                           // 支付金额（分）
	BalanceAmount     int64  `json:"balance_amount"`                       // 余额支付金额（分）
	UseBalance        int8   `orm:"default(0)" json:"use_balance"`         // 是否使用余额支付：0:否 1:是
	PaymentChannel    string `orm:"size(32)" json:"payment_channel"`       // 支付渠道
	TradeNo           string `orm:"size(64)" json:"trade_no"`              // 支付交易号
	VenueId           int64  `orm:"index" json:"venue_id"`                 // 场馆ID
	StoreId           int64  `orm:"index" json:"store_id"`                 // 门店ID
	StartTime         int64  `json:"start_time"`                           // 开始时间
	EndTime           int64  `json:"end_time"`                             // 结束时间
	CouponId          int64  `orm:"default(0)" json:"coupon_id"`           // 优惠券ID
	GroupBuyId        int64  `orm:"default(0)" json:"group_buy_id"`        // 团购券ID
	Remark            string `orm:"size(255)" json:"remark"`               // 备注
	IsRenew           int8   `orm:"default(0)" json:"is_renew"`            // 是否为续单：0:否 1:是
	OriginalBookingId int64  `orm:"default(0)" json:"original_booking_id"` // 原订单ID（续单时）

	// 兼容字段 - 不存储到数据库
	Type          int8   `orm:"-" json:"type"`           // 订单类型
	PaymentStatus int8   `orm:"-" json:"payment_status"` // 支付状态
	PaymentTime   int64  `orm:"-" json:"payment_time"`   // 支付时间
	CancelTime    int64  `orm:"-" json:"cancel_time"`    // 取消时间
	StoreName     string `orm:"-" json:"store_name"`     // 门店名称
}

// TableName 设置表名
func (b *Order) TableName() string {
	return "ss_order"
}

// GetBookingById 根据ID获取预约订单
func GetBookingById(id int64) (*Order, error) {
	order := &Order{BaseModel: BaseModel{Id: id}}
	o := orm.NewOrm()
	err := o.Read(order)
	if err == orm.ErrNoRows {
		return nil, nil
	}
	return order, err
}

// GetBookingList 获取预约订单列表
func GetBookingList(page, pageSize int, filters map[string]interface{}) ([]*Order, int64, error) {
	o := orm.NewOrm()
	qs := o.QueryTable(new(Order)).Filter("is_deleted", 0)

	// 应用过滤条件
	for k, v := range filters {
		if k == "status" {
			// 处理状态数组
			if statuses, ok := v.([]int8); ok && len(statuses) > 0 {
				qs = qs.Filter("status__in", statuses)
			} else {
				qs = qs.Filter("status", v)
			}
		} else {
			qs = qs.Filter(k, v)
		}
	}

	// 获取总数
	var total int64
	total, err := qs.Count()
	if err != nil {
		return nil, 0, err
	}

	// 分页查询
	var orders []*Order
	_, err = qs.OrderBy("-created_at").
		Limit(pageSize).
		Offset((page - 1) * pageSize).
		All(&orders)

	if err != nil {
		return nil, 0, err
	}

	return orders, total, err
}

// UpdateBooking 更新预约订单
func UpdateBooking(booking *Order) error {
	o := orm.NewOrm()
	order := (*Order)(booking)
	order.UpdatedAt = time.Now().Unix()
	_, err := o.Update(order)
	return err
}

// UpdateBookingTx 事务中更新预约订单
func UpdateBookingTx(tx orm.TxOrmer, booking *Order, fields ...string) (int64, error) {
	booking.UpdatedAt = time.Now().Unix()
	order := (*Order)(booking)
	return tx.Update(order, fields...)
}

// CreateBooking 创建预约订单
func CreateBooking(booking *Order) (int64, error) {
	o := orm.NewOrm()
	booking.CreatedAt = time.Now().Unix()
	booking.UpdatedAt = booking.CreatedAt
	id, err := o.Insert(booking)
	return id, err
}

// GetOrderList 获取订单列表
func GetOrderList(page, pageSize int, filters map[string]interface{}) ([]*Order, int64, *OrderStatistics, error) {
	o := orm.NewOrm()
	qs := o.QueryTable(new(Order))

	// 应用过滤条件
	if keyword, ok := filters["keyword"].(string); ok && keyword != "" {
		cond := orm.NewCondition()
		cond = cond.Or("order_no__contains", keyword)
		cond = cond.Or("user_name__contains", keyword)
		qs = qs.SetCond(cond)
	}
	if storeId, ok := filters["store_id"].(int64); ok && storeId > 0 {
		qs = qs.Filter("store_id", storeId)
	}
	if status, ok := filters["status"].(int8); ok && status > 0 {
		qs = qs.Filter("status", status)
	}
	if paymentStatus, ok := filters["payment_status"].(int8); ok && paymentStatus > 0 {
		qs = qs.Filter("payment_status", paymentStatus)
	}

	// 排除已删除的记录
	qs = qs.Filter("is_deleted", 0)

	// 获取总数
	total, _ := qs.Count()

	// 分页查询
	var orders []*Order
	_, _ = qs.OrderBy("-id").Limit(pageSize, (page-1)*pageSize).All(&orders)

	// 获取统计数据
	stats, err := GetOrderStatistics(0)

	return orders, total, stats, err
}

// OrderStatistics 订单统计数据
type OrderStatistics struct {
	TotalOrders   int64 `json:"total_orders"`   // 总订单数
	PendingOrders int64 `json:"pending_orders"` // 待处理订单数
	TodayOrders   int64 `json:"today_orders"`   // 今日订单数
	TotalAmount   int64 `json:"total_amount"`   // 总金额(分)
	TodayAmount   int64 `json:"today_amount"`   // 今日订单金额(分)
}

// GetActiveOrderByVenueId 根据场地ID获取当前有效的订单
func GetActiveOrderByVenueId(venueId int64, currentTime int64) (*Order, error) {
	return GetActiveOrderByVenueIdAndMemberId(venueId, 0, currentTime)
}

// GetActiveOrderByVenueIdAndMemberId 根据场地ID和会员ID获取当前有效的订单
func GetActiveOrderByVenueIdAndMemberId(venueId int64, memberId int64, currentTime int64) (*Order, error) {
	o := orm.NewOrm()
	order := &Order{}

	qs := o.QueryTable(new(Order)).
		Filter("venue_id", venueId).
		Filter("is_deleted", 0).
		Filter("status__in", 2). //已确认
		Filter("start_time__lte", currentTime).
		Filter("end_time__gte", currentTime)

	if memberId > 0 {
		qs = qs.Filter("member_id", memberId)
	}

	err := qs.OrderBy("-created_at").One(order)

	if err != nil {
		if err == orm.ErrNoRows {
			return nil, nil // 没有找到有效订单，这不是一个错误
		}
		return nil, err // 其他查询错误
	}

	return order, nil
}

// GetOrderStatistics 获取订单统计数据
func GetOrderStatistics(franchiseId int64) (*OrderStatistics, error) {
	o := orm.NewOrm()
	stats := &OrderStatistics{}

	// 构建基础查询条件
	whereClause := "is_deleted = 0"
	params := []interface{}{}

	// 如果是加盟商，添加加盟商过滤条件
	if franchiseId > 0 {
		whereClause += " AND franchise_id = ?"
		params = append(params, franchiseId)
	}

	// 获取总订单数和总金额
	err := o.Raw("SELECT COUNT(*) as total_orders, COALESCE(SUM(total_amount), 0) as total_amount FROM ss_order WHERE "+whereClause, params...).QueryRow(&stats.TotalOrders, &stats.TotalAmount)
	if err != nil {
		return nil, err
	}

	// 获取今日订单数和金额
	todayStart := time.Now().Format("2006-01-02") + " 00:00:00"
	todayEnd := time.Now().Format("2006-01-02") + " 23:59:59"
	todayParams := append(params, todayStart, todayEnd)
	err = o.Raw("SELECT COUNT(*) as today_orders, COALESCE(SUM(total_amount), 0) as today_amount FROM ss_order WHERE "+whereClause+" AND created_at >= ? AND created_at <= ?", todayParams...).QueryRow(&stats.TodayOrders, &stats.TodayAmount)
	if err != nil {
		return nil, err
	}

	// 获取待处理订单数
	pendingParams := append(params, 0) // 0 表示待处理状态
	err = o.Raw("SELECT COUNT(*) FROM ss_order WHERE "+whereClause+" AND status = ?", pendingParams...).QueryRow(&stats.PendingOrders)
	if err != nil {
		return nil, err
	}

	return stats, nil
}

// GetOrderById 根据ID获取订单
func GetOrderById(id int64) (*Order, error) {
	o := orm.NewOrm()
	order := &Order{BaseModel: BaseModel{Id: id}}
	err := o.Read(order)
	return order, err
}

// UpdateOrderStatus 更新订单状态
func UpdateOrderStatus(id int64, status int8, remark string, operator string) error {
	o := orm.NewOrm()
	order := &Order{BaseModel: BaseModel{Id: id}}
	if err := o.Read(order); err != nil {
		return err
	}

	order.Status = status
	order.Remark = remark
	order.UpdatedBy = operator
	order.UpdatedAt = time.Now().Unix()

	_, err := o.Update(order, "Status", "Remark", "UpdatedAt", "UpdatedBy")
	return err
}

// GetOrderByOrderNo 根据订单号获取订单
func GetOrderByOrderNo(orderNo string) (*Order, error) {
	o := orm.NewOrm()
	order := &Order{OrderNo: orderNo}
	err := o.Read(order, "OrderNo")
	return order, err
}

// OrderStatusDistribution 订单状态分布
type OrderStatusDistribution struct {
	Status     int8   `json:"status"`
	Count      int64  `json:"count"`
	Amount     int64  `json:"amount"`
	Percentage string `json:"percentage"`
}

// GetOrderStatusDistribution 获取订单状态分布
func GetOrderStatusDistribution(filters map[string]interface{}) ([]OrderStatusDistribution, error) {
	o := orm.NewOrm()
	sql := "SELECT status, COUNT(1) as count, SUM(total_amount) as amount FROM ss_order WHERE is_deleted = 0"

	// 应用过滤条件
	if storeId, ok := filters["store_id"].(int64); ok && storeId > 0 {
		sql += fmt.Sprintf(" AND store_id = %d", storeId)
	}
	if startTime, ok := filters["start_time"].(int64); ok {
		sql += fmt.Sprintf(" AND created_at >= %d", startTime)
	}
	if endTime, ok := filters["end_time"].(int64); ok {
		sql += fmt.Sprintf(" AND created_at <= %d", endTime)
	}

	sql += " GROUP BY status"

	var maps []orm.Params
	_, err := o.Raw(sql).Values(&maps)
	if err != nil {
		return nil, err
	}

	// 计算总数
	var total int64
	o.Raw("SELECT COUNT(1) FROM ss_order WHERE is_deleted = 0").QueryRow(&total)
	logs.Debug("GetOrderStatusDistribution:", maps, sql)
	// 构建结果
	var result []OrderStatusDistribution
	for _, m := range maps {
		status, _ := strconv.ParseInt(m["status"].(string), 10, 64)
		count, _ := strconv.ParseInt(m["count"].(string), 10, 64)
		amount, _ := strconv.ParseInt(m["amount"].(string), 10, 64)
		percentage := fmt.Sprintf("%.2f", float64(count)/float64(total)*100)

		result = append(result, OrderStatusDistribution{
			Status:     int8(status),
			Count:      count,
			Amount:     amount,
			Percentage: percentage,
		})
	}

	return result, nil
}

// PaymentTypeDistribution 支付方式分布
type PaymentTypeDistribution struct {
	Type       string `json:"type"`
	Count      int64  `json:"count"`
	Amount     int64  `json:"amount"`
	Percentage string `json:"percentage"`
}

// GetPaymentTypeDistribution 获取支付方式分布
func GetPaymentTypeDistribution(filters map[string]interface{}) ([]PaymentTypeDistribution, error) {
	o := orm.NewOrm()
	sql := "SELECT payment_channel, COUNT(1) as count, SUM(total_amount) as amount FROM ss_order WHERE is_deleted = 0"

	// 应用过滤条件
	if storeId, ok := filters["store_id"].(int64); ok && storeId > 0 {
		sql += fmt.Sprintf(" AND store_id = %d", storeId)
	}
	if startTime, ok := filters["start_time"].(int64); ok {
		sql += fmt.Sprintf(" AND created_at >= %d", startTime)
	}
	if endTime, ok := filters["end_time"].(int64); ok {
		sql += fmt.Sprintf(" AND created_at <= %d", endTime)
	}

	sql += " GROUP BY payment_channel"

	var maps []orm.Params
	_, err := o.Raw(sql).Values(&maps)
	if err != nil {
		return nil, err
	}

	// 计算总数
	var total int64
	o.Raw("SELECT COUNT(1) FROM ss_order WHERE is_deleted = 0").QueryRow(&total)

	logs.Debug("GetPaymentTypeDistribution:", maps, sql)
	// 构建结果
	var result []PaymentTypeDistribution
	for _, m := range maps {
		payType := m["payment_channel"].(string)
		count, _ := strconv.ParseInt(m["count"].(string), 10, 64)
		amount, _ := strconv.ParseInt(m["amount"].(string), 10, 64)
		percentage := fmt.Sprintf("%.2f", float64(count)/float64(total)*100)

		result = append(result, PaymentTypeDistribution{
			Type:       payType,
			Count:      count,
			Amount:     amount,
			Percentage: percentage,
		})
	}

	return result, nil
}

// CreateBookingTx 在事务中创建预约订单
func CreateBookingTx(tx orm.TxOrmer, booking *Order) (int64, error) {
	booking.BeforeInsert()
	return tx.Insert(booking)
}

// UpdateOrder 更新订单
func UpdateOrder(order *Order, fields ...string) error {
	o := orm.NewOrm()
	_, err := o.Update(order, fields...)
	return err
}

// UpdateOrderTx 事务中更新订单
func UpdateOrderTx(tx orm.TxOrmer, order *Order, fields ...string) (int64, error) {
	return tx.Update(order, fields...)
}

func FindPendingOrders(now int64) ([]*Order, error) {
	o := orm.NewOrm()
	var orders []*Order
	_, err := o.QueryTable(new(Order)).
		Filter("status", OrderStatusPending). // 状态为待确认
		Filter("start_time__lte", now).       // 开始时间早于当前时间
		Filter("is_deleted", 0).
		All(&orders)

	return orders, err
}

// FindOverdueConfirmedOrders 查找所有已确认且已结束的订单
func FindOverdueConfirmedOrders(currentTime int64) ([]*Order, error) {
	o := orm.NewOrm()
	var orders []*Order
	_, err := o.QueryTable(new(Order)).
		Filter("status", OrderStatusProcessing). // 状态为已确认
		Filter("end_time__lt", currentTime).     // 结束时间早于当前时间
		Filter("is_deleted", 0).
		All(&orders)

	return orders, err
}

// GetFirstUpcomingOrActiveOrder 获取指定场地的第一个即将开始或正在进行的订单
func GetFirstUpcomingOrActiveOrder(venueId, now int64) (*Order, error) {
	o := orm.NewOrm()
	var order Order
	err := o.QueryTable(new(Order)).
		Filter("venue_id", venueId).
		Filter("end_time__gte", now). // 订单尚未结束
		Filter("is_deleted", 0).
		Filter("status__in", 0, 1, 2). // 已支付或待确认或已确认
		OrderBy("start_time").         // 按开始时间升序排序
		Limit(1).                      // 只取第一条
		One(&order)

	if err == orm.ErrNoRows {
		return nil, nil // 没有找到订单，不认为是错误
	}
	return &order, err
}

// BatchUpdateOrderStatus 批量更新订单状态
// CreateOrderByAdmin 管理员代客下单
func CreateOrderByAdmin(franchiseId, storeId, venueId, memberId, startTime, endTime int64, remark, operator string) (*Order, error) {
	o := orm.NewOrm()

	// 1. 获取场地信息，以计算价格
	venue, err := GetVenueById(venueId)
	if err != nil || venue == nil {
		return nil, fmt.Errorf("场地不存在")
	}

	// 2. 检查场地在指定时间段内是否可用
	isAvailable, err := CheckVenueAvailability(venueId, startTime, endTime, 0)
	if err != nil {
		return nil, fmt.Errorf("检查场地可用性失败: %v", err)
	}
	if !isAvailable {
		return nil, fmt.Errorf("场地在指定时间段内已被占用")
	}

	// 3. 计算订单总金额
	duration := float64(endTime-startTime) / 3600 // 小时
	totalAmount := venue.HourPrice * duration
	member, err := GetMemberById(memberId, franchiseId)
	if err != nil || member == nil {
		return nil, fmt.Errorf("会员不存在")
	}

	// 4. 创建订单对象
	order := &Order{
		OrderNo:       GenerateOrderNoAdmin(),
		UserId:        memberId, // 管理员下单，没有前台用户ID
		MemberId:      memberId,
		Status:        OrderStatusProcessing, // 直接为已确认状态
		TotalAmount:   int64(totalAmount * 100),
		Phone:         member.Phone,
		UserName:      member.Name,
		PayAmount:     0, // 代客下单，默认为线下收款或免单，线上支付金额为0
		BalanceAmount: 0,
		UseBalance:    0,
		StoreId:       storeId,
		VenueId:       venueId,
		StartTime:     startTime,
		EndTime:       endTime,
		Remark:        remark,
	}
	order.CreatedBy = operator
	order.UpdatedBy = operator
	order.BeforeInsert()

	// 5. 保存订单
	_, err = o.Insert(order)
	if err != nil {
		return nil, err
	}

	return order, nil
}

// GenerateOrderNo 生成订单号
func GenerateOrderNoAdmin() string {
	return fmt.Sprintf("SO%s%d", time.Now().Format("20060102150405"), time.Now().UnixNano()%1000)
}

func BatchUpdateOrderStatus(orderIDs []int64, status int8) (int64, error) {
	if len(orderIDs) == 0 {
		return 0, nil
	}
	o := orm.NewOrm()
	num, err := o.QueryTable(new(Order)).
		Filter("id__in", orderIDs).
		Update(orm.Params{
			"status":     status,
			"updated_at": time.Now().Unix(),
		})
	return num, err
}

// RescheduleOrder handles the logic of rescheduling an order.
func RescheduleOrder(originalOrderID, newVenueID, operatorID int64) (*Order, error) {
	o := orm.NewOrm()

	// 1. Get the original order
	originalOrder, err := GetOrderById(originalOrderID)
	if err != nil {
		return nil, fmt.Errorf("failed to get original order: %v", err)
	}
	if originalOrder == nil {
		return nil, fmt.Errorf("original order not found")
	}

	// 2. Check if the order can be rescheduled (e.g., must be 'completed')
	if originalOrder.Status != OrderStatusCompleted { // Assuming OrderStatusCompleted is a valid status constant
		return nil, fmt.Errorf("only completed orders can be rescheduled")
	}

	// 3. 检查新场地在指定时间段内是否可用
	isAvailable, err := CheckVenueAvailability(newVenueID, originalOrder.StartTime, originalOrder.EndTime, originalOrder.Id)
	if err != nil {
		return nil, fmt.Errorf("检查新场地可用性失败: %v", err)
	}
	if !isAvailable {
		return nil, fmt.Errorf("新场地在指定时间段内已被占用")
	}

	// 4. Start a transaction
	tx, err := o.Begin()
	if err != nil {
		return nil, fmt.Errorf("failed to start transaction: %v", err)
	}

	// 5. Create a new order with the new details but same time
	newOrder := &Order{
		OrderNo:           GenerateOrderNoAdmin(), // Use existing admin order no generator
		UserId:            originalOrder.UserId,
		MemberId:          originalOrder.MemberId,
		UserName:          originalOrder.UserName,
		Phone:             originalOrder.Phone,
		Status:            OrderStatusProcessing,     // New order starts as pending
		TotalAmount:       originalOrder.TotalAmount, // Or recalculate based on new venue
		PayAmount:         originalOrder.PayAmount,
		BalanceAmount:     originalOrder.BalanceAmount,
		UseBalance:        originalOrder.UseBalance,
		PaymentChannel:    originalOrder.PaymentChannel,
		TradeNo:           "", // New order has no trade number yet
		VenueId:           newVenueID,
		StoreId:           originalOrder.StoreId,   // Assuming same store
		StartTime:         originalOrder.StartTime, // Keep original time
		EndTime:           originalOrder.EndTime,   // Keep original time
		CouponId:          0,                       // Coupon from original order is considered used
		GroupBuyId:        0,                       // Group buy from original order is considered used
		Remark:            fmt.Sprintf("改签自订单：%s", originalOrder.OrderNo),
		IsRenew:           0,
		OriginalBookingId: originalOrderID,
	}
	newOrder.CreatedBy = fmt.Sprintf("user-%d", operatorID)
	newOrder.UpdatedBy = fmt.Sprintf("user-%d", operatorID)
	newOrder.CreatedAt = time.Now().Unix()
	newOrder.UpdatedAt = time.Now().Unix()

	_, err = tx.Insert(newOrder)
	if err != nil {
		tx.Rollback()
		return nil, fmt.Errorf("failed to create new order: %v", err)
	}

	// 6. Update the old order's status to 'rescheduled' or similar
	originalOrder.Status = OrderStatusRescheduled // Assuming OrderStatusRescheduled is a valid status constant
	originalOrder.Remark = fmt.Sprintf("%s 改签到新订单：%s.", originalOrder.Remark, newOrder.OrderNo)
	originalOrder.UpdatedAt = time.Now().Unix()

	_, err = tx.Update(originalOrder, "Status", "Remark", "UpdatedAt")
	if err != nil {
		tx.Rollback()
		return nil, fmt.Errorf("failed to update original order: %v", err)
	}

	// 7. Commit the transaction
	err = tx.Commit()
	if err != nil {
		return nil, fmt.Errorf("failed to commit transaction: %v", err)
	}

	return newOrder, nil
}

func GetOrdersForVenueBetween(venueID int64, startTime, endTime int64) ([]*Order, error) {
	var orders []*Order
	_, err := orm.NewOrm().QueryTable(new(Order)).
		Filter("venue_id", venueID).
		Filter("status__in", []int8{OrderStatusProcessing, OrderStatusPending}).
		Filter("end_time__gte", startTime).
		All(&orders)
	if err != nil {
		return nil, err
	}
	return orders, nil
}

// CheckVenueAvailability 检查场地在指定时间段内是否可用
func CheckVenueAvailability(venueID int64, startTime, endTime int64, excludeOrderID int64) (bool, error) {
	o := orm.NewOrm()

	// 查询在指定时间段内有冲突的订单
	qs := o.QueryTable(new(Order)).
		Filter("venue_id", venueID).
		Filter("is_deleted", 0).
		Filter("status__in", []int8{OrderStatusProcessing, OrderStatusPending}).
		Filter("start_time__lt", endTime).
		Filter("end_time__gt", startTime)

	// 如果指定了需要排除的订单ID（如改签场景）
	if excludeOrderID > 0 {
		qs = qs.Exclude("id", excludeOrderID)
	}

	count, err := qs.Count()
	if err != nil {
		return false, err
	}

	return count == 0, nil
}
